/*
 * Copyright (c) 2009 Jesse McLaughlin (nzjess@gmail.com)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *         http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.travelfusion.xmlclient.ri;

import javax.xml.stream.XMLInputFactory;

import org.travelfusion.xmlclient.TfXClient;
import org.travelfusion.xmlclient.cache.CacheProvider;
import org.travelfusion.xmlclient.handler.HandlerPipelineTypeRegistry;
import org.travelfusion.xmlclient.impl.BaseClientFactory;
import org.travelfusion.xmlclient.impl.login.LoginBean;
import org.travelfusion.xmlclient.login.Login;
import org.travelfusion.xmlclient.login.LoginManager;
import org.travelfusion.xmlclient.ri.handler.misc.FindAlternativeFlightsHandler;
import org.travelfusion.xmlclient.ri.handler.misc.FindCheapestPricesHandler;
import org.travelfusion.xmlclient.ri.handler.misc.GetAirlinesDataHandler;
import org.travelfusion.xmlclient.ri.handler.misc.GetAirportsDataHandler;
import org.travelfusion.xmlclient.ri.handler.misc.GetAirportsPageInfoHandler;
import org.travelfusion.xmlclient.ri.handler.misc.GetCitiesPageInfoHandler;
import org.travelfusion.xmlclient.ri.handler.misc.GetCurrenciesHandler;
import org.travelfusion.xmlclient.ri.handler.misc.GetProductTypesHandler;
import org.travelfusion.xmlclient.ri.handler.misc.GetSupplierRoutesHandler;
import org.travelfusion.xmlclient.ri.handler.misc.ListAffiliateSuppliersHandler;
import org.travelfusion.xmlclient.ri.handler.misc.ListSuppliersHandler;
import org.travelfusion.xmlclient.ri.handler.misc.SuppliersListViewHandler;
import org.travelfusion.xmlclient.ri.handler.plane.CheckRoutingHandler;
import org.travelfusion.xmlclient.ri.handler.plane.ProcessDetailsHandler;
import org.travelfusion.xmlclient.ri.handler.plane.StartRoutingHandler;
import org.travelfusion.xmlclient.ri.module.StandardModule;
import org.travelfusion.xmlclient.ri.xobject.misc.XGetAirlinesDataRequest;
import org.travelfusion.xmlclient.ri.xobject.misc.XGetAirportsDataRequest;
import org.travelfusion.xmlclient.ri.xobject.misc.XGetAirportsPageInfoRequest;
import org.travelfusion.xmlclient.ri.xobject.misc.XGetCitiesPageInfoRequest;
import org.travelfusion.xmlclient.ri.xobject.misc.XGetCurrenciesRequest;
import org.travelfusion.xmlclient.ri.xobject.misc.XGetSupplierRoutesRequest;
import org.travelfusion.xmlclient.ri.xobject.misc.XListAffiliateSuppliersRequest;
import org.travelfusion.xmlclient.ri.xobject.misc.XListSuppliersRequest;
import org.travelfusion.xmlclient.ri.xobject.misc.XSupplierListViewRequest;
import org.travelfusion.xmlclient.util.TfXAPIUtil;

import com.google.inject.Module;

/**
 * Create an instance of this class in order to create a {@link TfXClient} instance configured to use the handler
 * implementations in this library.
 * 
 * @author Jesse McLaughlin (nzjess@gmail.com)
 */
public class TfXClientFactory extends BaseClientFactory {

  /**
   * Create a client factory using the standard-usage component implementations, via the {@link StandardModule} module.
   * The given loginId will be bound for you.
   */
  public TfXClientFactory(String loginId) {
    this(new LoginBean(loginId), new StandardModule());
  }

  /**
   * Create a client factory using the standard-usage component implementations, via the {@link StandardModule} module.
   * The given {@link Login} instance will be bound for you.
   */
  public TfXClientFactory(Login login) {
    super(login, new StandardModule());
  }

  /**
   * Create a client factory using a custom set of Guice modules. One of your modules should configure an appropriate
   * {@link LoginManager}. The given loginId will be bound for you.
   */
  public TfXClientFactory(String loginId, Module... modules) {
    this(new LoginBean(loginId), modules);
  }

  /**
   * Create a client factory using a custom set of Guice modules. One of your modules should configure an appropriate
   * {@link LoginManager}. The given {@link Login} instance will be bound for you.
   * <p>
   * Note that this factory assumes a {@link HandlerPipelineTypeRegistry} has been configured, as well as an instance of
   * {@link XMLInputFactory}. The {@link StandardModule} module satisfies these requirements.
   */
  public TfXClientFactory(Login login, Module... modules) {
    super(login, modules);
  }

  /**
   * Create a client factory using a custom set of Guice modules. One of your modules should configure an appropriate
   * {@link LoginManager}.
   * <p>
   * Note that this factory assumes a {@link HandlerPipelineTypeRegistry} has been configured, as well as an instance of
   * {@link XMLInputFactory}. The {@link StandardModule} module satisfies these requirements.
   */
  public TfXClientFactory(Module... modules) {
    super(modules);
  }

  /**
   * Configure the command handlers implemented by this library, and set up caching policies.
   */
  @Override
  protected void configureFactory() {
    // obtain type registry
    HandlerPipelineTypeRegistry registry = getInjector().getInstance(HandlerPipelineTypeRegistry.class);

    // register plane commands
    registry.registerHandlerType(StartRoutingHandler.class);
    registry.registerHandlerType(CheckRoutingHandler.class);
    registry.registerHandlerType(ProcessDetailsHandler.class);

    // register misc commands
    registry.registerHandlerType(GetAirlinesDataHandler.class);
    registry.registerHandlerType(GetAirportsDataHandler.class);
    registry.registerHandlerType(GetCurrenciesHandler.class);
    registry.registerHandlerType(GetAirportsPageInfoHandler.class);
    registry.registerHandlerType(GetCitiesPageInfoHandler.class);
    registry.registerHandlerType(ListSuppliersHandler.class);
    registry.registerHandlerType(SuppliersListViewHandler.class);
    registry.registerHandlerType(ListAffiliateSuppliersHandler.class);
    registry.registerHandlerType(FindCheapestPricesHandler.class);
    registry.registerHandlerType(FindAlternativeFlightsHandler.class);
    registry.registerHandlerType(GetProductTypesHandler.class);
    registry.registerHandlerType(GetSupplierRoutesHandler.class);

    // obtain cache provider
    CacheProvider cache = getInjector().getInstance(CacheProvider.class);

    // configure cache policies
    cache.getCachePolicy(XGetAirportsDataRequest.class).setTimeoutMillis(TfXAPIUtil.MILLIS_PER_DAY);
    cache.getCachePolicy(XGetAirlinesDataRequest.class).setTimeoutMillis(TfXAPIUtil.MILLIS_PER_DAY);
    cache.getCachePolicy(XGetCurrenciesRequest.class).setTimeoutMillis(TfXAPIUtil.MILLIS_PER_DAY);
    cache.getCachePolicy(XGetAirportsPageInfoRequest.class).setTimeoutMillis(TfXAPIUtil.MILLIS_PER_DAY);
    cache.getCachePolicy(XGetCitiesPageInfoRequest.class).setTimeoutMillis(TfXAPIUtil.MILLIS_PER_DAY);
    cache.getCachePolicy(XListSuppliersRequest.class).setTimeoutMillis(TfXAPIUtil.MILLIS_PER_DAY);
    cache.getCachePolicy(XSupplierListViewRequest.class).setTimeoutMillis(TfXAPIUtil.MILLIS_PER_DAY);
    cache.getCachePolicy(XListAffiliateSuppliersRequest.class).setTimeoutMillis(TfXAPIUtil.MILLIS_PER_DAY);
    cache.getCachePolicy(XGetSupplierRoutesRequest.class).setTimeoutMillis(TfXAPIUtil.MILLIS_PER_DAY);
  }
}

